package com.jdwx.opengl.kotlin2

import androidx.annotation.RestrictTo
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.startCoroutine

/**
 * 协程是轻量级的
 */
fun testThread() {
    val jobs = List(100_1000) {
        Thread({
            Thread.sleep(1000L)
            print(".")
        })
    }
    jobs.forEach {
        it.start()
    }
    jobs.forEach {
        it.join()
    }
}
fun finallyCancelDemo() = runBlocking {
    val job = launch(){
        try {
            withTimeout(3000){
                repeat(1000) { i ->
                    println("I'm sleeping $i ...")
                    delay(500L)
                }
            }

        } finally {
            println("I'm running finally")
            delay(1000L)
            println("And I've delayed for 1 sec ?")
        }
    }
    delay(2000L)
    println("Before cancel, Job is alive: ${job.isActive} Job is completed: ${job.isCompleted}")
    job.cancel() 
    println("After cancel, Job is alive: ${job.isActive} Job is completed: ${job.isCompleted}")
    delay(2000L)
    println("main: Now I can quit.")
}
fun testChildrenCoroutine()= runBlocking<Unit> {
    val request = launch() {
        val job1 = launch() {
            println("job1: 独立的协程上下文!")
            delay(1000)
            println("job1: 不会受到request.cancel()的影响")
        }

        // 继承父上下文:request的context
        val job2 = launch(coroutineContext) {
            println("job2: 是request coroutine的子协程")
            delay(1000)
            println("job2: 当request.cancel()，job2也会被取消")
        }
        job1.join()
        job2.join()
    }
    delay(500)
    request.cancel()
    delay(1000)
    println("main: Who has survived request cancellation?")
}
//fun main(){
//    //testThread()
//    //finallyCancelDemo()
//    //val ctx1 = newSingleThreadContext("线程A")
//    testChildrenCoroutine()
//
//}
//fun main(args: Array<String>) = runBlocking<Unit> {
//    // 创建一个协程，模拟请求
//    val request = launch(coroutineContext) { // 使用 runBlocking 的上下文
//        // 在 CommonPool 里新建 CPU 敏感的子任务!!!
//        val job = launch(coroutineContext + CommonPool) {
//            println("job: I am a child of the request coroutine, but with a different dispatcher")
//            delay(1000)
//            println("job: I will not execute this line if my parent request is cancelled")
//        }
//        job.join() // 当子任务完成时，请求结束
//    }
//    delay(500)
//    request.cancel() // 取消请求
//    delay(1000) // 延时一秒，看看发生了什么
//    println("main: Who has survived request cancellation?")
//
//    repeat(3) { i -> // 创建一小批子协程
//        launch(coroutineContext)  {
//            delay((i + 1) * 200L) // 延迟 200ms, 400ms, 600ms
//            println("Coroutine $i is done")
//        }
//    }
//    fun a(i:Int){
//
//        println( i )
//
//    }
//    repeat(3) {
//        launch(coroutineContext)  {
//            delay((it + 1) * 200L) // 延迟 200ms, 400ms, 600ms
//            println("Coroutine $it is done")
//        }
//    }

//}
fun testClosingAndIterationChannels() = runBlocking {
    val channel = Channel<Int>()
    launch {
        for (x in 1..5)
            channel.send(x * x)
        channel.close() // 我们结束 sending
        }
// 打印通道中的值，直到通道关闭
    for (x in channel)
        println(x)
    println("Done!")
}


fun main(args: Array<String>) = runBlocking<Unit> {
//    //log("Started main coroutine")
//    // 运行两个后台计算协程
//    //协同程序的名字
//    val v1 = async(CoroutineName("v1coroutine")) {
//        delay(500)
//        //log("Computing v1")
//        println("Computing v1")
//        252
//    }
//    //协同程序的名字
//    val v2 = async(CoroutineName("v2coroutine")) {
//        delay(1000)
//        //log("Computing v2")
//        println("Computing v2")
//        6
//    }
//    println("The answer for v1 / v2 = ${v1.await() / v2.await()}")
//    //log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
//
    //testClosingAndIterationChannels()

    //生产者  / 消费者
//    fun produceSquares() = produce<Int> {
//        for (x in 1..5)
//            send(x * x)
//
//    }
//    val squares = produceSquares()
//    squares.consumeEach {
//        println(it)
//    }
//    println("Done!")

    //管道生产无限序列
//    fun produceNumbers() = produce<Long>() {
//        var x = 1L
//        while (true)
//            send(x++) // infinite stream of integers starting from 1
//    }
//    val squares = produceNumbers()
////    squares.consumeEach {
////        println( it )
////    }
//    for (i in 1000..1006){
//        var result  = squares.receive()
//        println("result=$result")
//    }
//    squares.cancel();
//    println("Done!")

    //管道与无穷指数序列

    fun numbersProducer(context: CoroutineContext, start: Int) = produce<Int>(context) {
        var n = start
        while ( true ) {
            send(n++) // infinite stream of integers from start
        }

    }

    fun filterPrimes(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
        for (x in numbers) {
            print( "x=$x===;;")
            if (x % prime != 0) {
                println( "x=$x;prime=$prime")
                send(x)
            }
        }
    }
//
//    2 3 4 5 6 7 8 9 10
//    2
//
//    3 5 7 9
//    3
//
//    5 7
//    5
//
//    7


    //var a = GlobalScope.coroutineContext
    fun producePrimesSequences() = runBlocking {
        var producerJob = numbersProducer(coroutineContext, 2)
        for (i in 1..5){
            var prime = producerJob.receive()
            print("${prime} \t")
            producerJob = filterPrimes(coroutineContext, producerJob, prime)

        }

    }

    //producePrimesSequences()
    //coroutineContext.cancelChildren()

    val channel = Channel<Int>(4) // 创建一个缓冲区容量为4的通道
    launch{
        repeat(10) {
            println("Sending $it")
            channel.send(it) // 当缓冲区已满的时候， send将会挂起
        }
    }

    launch {
        while ( true ){
            print( channel.receive() )
        }
    }





}